package notesDetection.GUI;


import javax.swing.*;

import notesDetection.MusicAnalyzer.AnalyzeMusicFile.AnalysisPreferences;

import java.awt.*;
import java.awt.event.*;

public class AlgorithmSettings implements ActionListener {

	private JDialog _mainFrame;
    private JPanel panelFileBrowse;
    private JPanel pnlSouth;
    private JPanel pnlCenterGrid;
    private JPanel headerPanel;
    private JLabel headerText;
    
    private JButton setToDefault;
    private JSeparator buttonSeparator;
    private JButton buttonOk;
    private JButton buttonCancel;
    private JButton buttonApply;
    
    //	All configurations
    private JTextArea textDelta;
    protected JTextField fieldDelta;
    
    private JTextArea textTau;
    protected JTextField fieldTau;
    
    private JTextArea textWindowSize;
    protected JTextField fieldWindowSize;
    
    private JTextArea textAdvanceFactor;
    protected JTextField fieldAdvanceFactor;

    private JTextArea textSubSegments;
    protected JTextField fieldSubSegments;
    
    private JTextArea textQuietThreshold;
    protected JTextField fieldQuietThreshold;
    
    //	End of GUI Elements

	protected final double DEFAULT_DELTA;
	protected final double DEFAULT_TAU;
	protected final double DEFAULT_WINDOW_SIZE;
	protected final double DEFAULT_WINDOW_ADVANCE;
	protected final int DEFAULT_SUB_SEGMENTS;

	private double _lastDelta;
	private double _lastTau;
	private double _lastWindowSize;
	private double _lastWindowAdvance;
	private int _lastSubSegments;
	
	private AnalysisPreferences _mode;
	
	
    public AlgorithmSettings(JFrame frame, String name, AnalysisPreferences mode, double delta, double tau,
    		double windowSizeSec, double windowAdvanceSec, int numberOfSubSegments, double quietThreshold) {
 
    	DEFAULT_DELTA = _lastDelta = delta;
    	DEFAULT_TAU = _lastTau = tau;
    	DEFAULT_WINDOW_SIZE = _lastWindowSize = windowSizeSec;
    	DEFAULT_WINDOW_ADVANCE = _lastWindowAdvance = windowAdvanceSec;
    	DEFAULT_SUB_SEGMENTS = _lastSubSegments = numberOfSubSegments;
    	
    	_mode = mode;
    	
        _mainFrame = new JDialog(frame, name); //create Frame
        //	Initialize panels!
        
        panelFileBrowse = new JPanel(); // North quadrant 
        pnlSouth = new JPanel(); // South quadrant
        
        //	"0" means flexible number of rows
        GridLayout gridConfig = new GridLayout(0, 2, 20, 30);
        
        pnlCenterGrid = new JPanel(gridConfig); // Center quadrant          

         
        headerPanel = new JPanel();
        headerText = new JLabel(name);
        headerText.setForeground(Color.BLUE);
        headerPanel.add(headerText);
        
        setToDefault = new JButton("DEFAULT");
        setToDefault.addActionListener(new SetToDefault());

        buttonSeparator = new JSeparator();
        buttonSeparator.setPreferredSize(new Dimension(20, 10));
        buttonSeparator.setBackground(_mainFrame.getBackground());
        
        buttonOk = new JButton("OK");
        buttonOk.addActionListener(new SaveSettingsAndExit());
        
        buttonCancel = new JButton("Cancel");
        buttonCancel.addActionListener(new CancelSettings());
        
        buttonApply = new JButton("Apply");
        buttonApply.addActionListener(new SaveSettings());
        
        //	Create configurations panels
        
        Color mainFrameColor = _mainFrame.getBackground();
        Dimension fieldsDimension = new Dimension(150, 20);
        
        //	DELTA
        textDelta = new JTextArea("DELTA");
        textDelta.setBackground(mainFrameColor);
        textDelta.setEditable(false);
        
        fieldDelta = new JTextField(String.valueOf(delta));
        fieldDelta.setPreferredSize(fieldsDimension);
        
        //	TAU
        textTau = new JTextArea("Relative TAU");
        textTau.setBackground(mainFrameColor);
        textTau.setEditable(false);
        
        fieldTau = new JTextField(String.valueOf(tau));
        fieldTau.setPreferredSize(fieldsDimension);
        
        //	Window size
        textWindowSize = new JTextArea("Window size (sec)");
        textWindowSize.setBackground(mainFrameColor);
        textWindowSize.setEditable(false);
        
        fieldWindowSize = new JTextField(String.valueOf(windowSizeSec));
        fieldWindowSize.setPreferredSize(fieldsDimension);
        
        //	Advance Factor
        textAdvanceFactor = new JTextArea("Window advance (sec)");
        textAdvanceFactor.setBackground(mainFrameColor);
        textAdvanceFactor.setEditable(false);
        
        fieldAdvanceFactor = new JTextField(String.valueOf(windowAdvanceSec));
        fieldAdvanceFactor.setPreferredSize(fieldsDimension);
        
        //	Number of sub-segments
        textSubSegments = new JTextArea("Sub segments #");
        textSubSegments.setBackground(mainFrameColor);
        textSubSegments.setEditable(false);
        
        fieldSubSegments = new JTextField(String.valueOf(numberOfSubSegments));
        fieldSubSegments.setPreferredSize(fieldsDimension);
        
        textQuietThreshold = new JTextArea("Quiet threshold");
        textQuietThreshold.setBackground(mainFrameColor);
        textQuietThreshold.setEditable(false);
        
        fieldQuietThreshold = new JTextField(String.valueOf(quietThreshold));
        fieldQuietThreshold.setPreferredSize(fieldsDimension);        
        

        pnlCenterGrid.add(textDelta);
        pnlCenterGrid.add(fieldDelta);
        pnlCenterGrid.add(textTau);
        pnlCenterGrid.add(fieldTau);
        pnlCenterGrid.add(textWindowSize);
        pnlCenterGrid.add(fieldWindowSize);
        pnlCenterGrid.add(textAdvanceFactor);
        pnlCenterGrid.add(fieldAdvanceFactor);
        pnlCenterGrid.add(textSubSegments);
        pnlCenterGrid.add(fieldSubSegments);
        pnlCenterGrid.add(textQuietThreshold);
        pnlCenterGrid.add(fieldQuietThreshold);
        
        pnlSouth.add(setToDefault);
        pnlSouth.add(buttonSeparator);
        pnlSouth.add(buttonOk);
        pnlSouth.add(buttonCancel);
        pnlSouth.add(buttonApply);
        
        _mainFrame.setPreferredSize(new Dimension(350, 330));
        
        // Setup Main Frame
        _mainFrame.getContentPane().setLayout(new BorderLayout());
        _mainFrame.getContentPane().add(panelFileBrowse, BorderLayout.NORTH);
        _mainFrame.getContentPane().add(pnlCenterGrid, BorderLayout.CENTER);	
        _mainFrame.getContentPane().add(pnlSouth, BorderLayout.SOUTH);
        
        //String _currentDir = new File("").getAbsolutePath();
        //String iconRelativePath = "\\bin\\notesDetection\\GUI\\resources\\noteIconInverse.jpg";
        
        _mainFrame.setIconImage(LogoImage.loadImage(getClass().getResource("/notesDetection/GUI/resources/noteIconInverse.jpg")));
        
    	};


	private class SetToDefault implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			
			loadValues(DEFAULT_DELTA, DEFAULT_TAU, DEFAULT_WINDOW_SIZE,
					DEFAULT_WINDOW_ADVANCE, DEFAULT_SUB_SEGMENTS);
			
		}
		
	}
	
	private class SaveSettings implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent ev) {
			
			double tryDelta;
			double tryTau;
			double tryWindowSize;
			double tryAdvanceFactor;
			int trySubSegments;
			
			try
			{
				tryDelta = Double.parseDouble(fieldDelta.getText());
				tryTau = Double.parseDouble(fieldTau.getText());
				tryWindowSize = Double.parseDouble(fieldWindowSize.getText());
				tryAdvanceFactor = Double.parseDouble(fieldAdvanceFactor.getText());
				trySubSegments = Integer.parseInt(fieldSubSegments.getText());
			}
			catch(Exception ex)
			{
				SetErrorIndicator(true);
				return;
			}
			if(!isValidConfigurationInternal(tryDelta, tryTau, tryWindowSize, tryAdvanceFactor,
					trySubSegments, _mode))
			{
				SetErrorIndicator(true);
				return;
			}
			//	All values are OK, apply:
			_lastDelta = tryDelta;
			_lastTau = tryTau;
			_lastWindowSize = tryWindowSize;
			_lastWindowAdvance = tryAdvanceFactor;
			_lastSubSegments = trySubSegments;
			
			SetErrorIndicator(false);
			
		}
	}
	
	private class SaveSettingsAndExit implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent ev) {
			
			double tryDelta;
			double tryTau;
			double tryWindowSize;
			double tryAdvanceFactor;
			int trySubSegments;
			
			try
			{
				tryDelta = Double.parseDouble(fieldDelta.getText());
				tryTau = Double.parseDouble(fieldTau.getText());
				tryWindowSize = Double.parseDouble(fieldWindowSize.getText());
				tryAdvanceFactor = Double.parseDouble(fieldAdvanceFactor.getText());
				trySubSegments = Integer.parseInt(fieldSubSegments.getText());
			}
			catch(Exception ex)
			{
				SetErrorIndicator(true);
				return;
			}
			if(!isValidConfigurationInternal(tryDelta, tryTau, tryWindowSize, tryAdvanceFactor,
					trySubSegments, _mode))
			{
				SetErrorIndicator(true);
				return;
			}
			//	All values are OK, apply:
			_lastDelta = tryDelta;
			_lastTau = tryTau;
			_lastWindowSize = tryWindowSize;
			_lastWindowAdvance = tryAdvanceFactor;
			_lastSubSegments = trySubSegments;
			
			SetErrorIndicator(false);
			_mainFrame.setVisible(false);
			
		}
	}
	
	private class CancelSettings implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent ev) {
			
			SetErrorIndicator(false);
			loadValues(_lastDelta, _lastTau, _lastWindowSize,
					_lastWindowAdvance, _lastSubSegments);
			_mainFrame.setVisible(false);
			
		}
	}
	
	private void loadValues(double delta, double tau, double windowSize,
			double advanceFactor, int subSegments)
	{
		fieldDelta.setText(String.valueOf(delta));
		fieldTau.setText(String.valueOf(tau));
		fieldWindowSize.setText(String.valueOf(windowSize));
		fieldAdvanceFactor.setText(String.valueOf(advanceFactor));
		fieldSubSegments.setText(String.valueOf(subSegments));
	}
	
	private void SetErrorIndicator(boolean isError)
	{
		buttonApply.setBackground(isError ? Color.RED : setToDefault.getBackground());		
	}
	
	private boolean isSynced()
	{
		try
		{
			if(_lastDelta == Double.parseDouble(fieldDelta.getText()) &&
					_lastTau == Double.parseDouble(fieldTau.getText()) &&
					_lastWindowSize == Double.parseDouble(fieldWindowSize.getText()) &&
					(_lastWindowAdvance == Double.parseDouble(fieldAdvanceFactor.getText()) || (Double.isNaN(_lastWindowAdvance) && Double.isNaN(Double.parseDouble(fieldAdvanceFactor.getText())))) &&
					_lastSubSegments == Integer.parseInt(fieldSubSegments.getText()))
			{
				return true;
			}

		}
		catch(Exception ex)
		{
		}
		return false;
	}
	
	private	boolean isValidConfigurationInternal(
			double delta, double tau, double windowSize,
			double advanceFactor, int subSegments, AnalysisPreferences analysisMode)
	{
		if(analysisMode == AnalysisPreferences.Compression)
		{
			advanceFactor = windowSize;
		}
		if(delta <=0 || tau <=0 || advanceFactor <=0 || windowSize <= 0 || subSegments <= 0)
		{
			//_lastError = "All configurations must be positive!";
			return false;
		}
		switch(analysisMode)
		{
		case Notes:
			if(subSegments != 1 || advanceFactor > windowSize)
			{
				return false;
			}
			break;
		case Compression:
			if(advanceFactor > windowSize)
			{
				//_lastError = "Advance factor must be <= window size";
				return false;
			}
			break;
		default:
			break;
		}
		
		return true;
	}
	
	public boolean isValidConfiguration(
			double delta, double tau, double windowSize,
			double advanceFactor, int subSegments, AnalysisPreferences analysisMode)
	{
		if(!isSynced())
		{
			return false;
		}
		return isValidConfigurationInternal(delta, tau, windowSize, advanceFactor, subSegments, analysisMode);

	}


	@Override
	public void actionPerformed(ActionEvent arg0) {
        // Display Frame
		//loadValues(_lastDelta, _lastTau, _lastWindowSize,
		//		_lastWindowAdvance, _lastSubSegments);
		_mainFrame.setResizable(false);
    	_mainFrame.pack(); //Adjusts panel to components for display
    	_mainFrame.setVisible(true);
	}
	
	//	All throwing exception in case of failure...
	public double getDelta()
	{
		return _lastDelta;
	}
	
	public double getTau()
	{
		return _lastTau;
	}
	
	public double getWindowSize()
	{
		return _lastWindowSize;
	}
	
	public double getAdvanceFactor()
	{
		return _lastWindowAdvance;
	}
	
	public int getSubSegments()
	{
		return _lastSubSegments;
	}
	
}
